/*
 * MIT License
 * 
 * Copyright (c) 2024-2025 milkpotatoes
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef SRC_JS_UTILS_INCLUDE_JS_PROCESS_H
#define SRC_JS_UTILS_INCLUDE_JS_PROCESS_H

#include <atomic>
#include <uv.h>

#include "napi/native_api.h"  // IWYU pragma: keep

class JsProcess
{
public:
    static napi_value Init(napi_env env, napi_value global, int argc, int index, const char *argv[]);
    inline static int GetExitCode() { return exitCode_.load(); }

private:
    class UvPollEventsCallback {
        public:
        UvPollEventsCallback(napi_env env): env_(env) {}
        ~UvPollEventsCallback();
        void Invoke(uv_poll_t* handle, int status, int events);
        napi_env env_;
        napi_ref error_{};
        napi_ref readable_{};
        napi_ref writable_{};
        napi_ref disconnect_{};
        napi_ref prioritized_{};
    };
    static napi_value InitSignalMap(napi_env env);
    static napi_value InitEnv(napi_env env);

    __attribute__((noreturn)) static napi_value Abort(napi_env, napi_callback_info);
    __attribute__((noreturn)) static napi_value Exit(napi_env env, napi_callback_info info);
    static napi_value Cwd(napi_env env, napi_callback_info);
    static napi_value ChDir(napi_env env, napi_callback_info info);
    static napi_value GetArch(napi_env env, napi_callback_info);
    static napi_value SetExitCode(napi_env env, napi_callback_info info);

    static napi_value GetPid(napi_env env, napi_callback_info);
    static napi_value GetPPid(napi_env env, napi_callback_info);
    static napi_value GetEGid(napi_env env, napi_callback_info);
    static napi_value GetEUid(napi_env env, napi_callback_info);
    static napi_value GetGid(napi_env env, napi_callback_info);
    static napi_value GetGroups(napi_env env, napi_callback_info);
    static napi_value GetUid(napi_env env, napi_callback_info);

    static napi_value InnerKill(napi_env env, napi_callback_info info);
    static napi_value InnerGetEnviron(napi_env env, napi_callback_info info);
    static napi_value InnerGetEnv(napi_env env, napi_callback_info info);
    static napi_value InnerSetEnv(napi_env env, napi_callback_info info);
    static napi_value InnerUnsetEnv(napi_env env, napi_callback_info info);
    static napi_value InnerReadFd(napi_env env, napi_callback_info info);
    static napi_value InnerGetTitle(napi_env env, napi_callback_info info);
    static napi_value InnerSetTitle(napi_env env, napi_callback_info info);

    static std::atomic<int> exitCode_;
    JsProcess();
};

#endif /* SRC_JS_UTILS_INCLUDE_JS_PROCESS_H */